package model;

import java.util.ArrayList;
import java.util.LinkedList;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.tiled.TiledMap;

public final class Mapa {

    private TiledMap mapa;
    private LinkedList<Integer> tiles;
    private static int WIDTH;
    private static int HEIGHT;
    private static int TILE_WIDTH;
    private static int TILE_HEIGHT;
    private static Vertice[][] mapInfo;
    private static Mensagem branco;
    private static Mensagem preto;
    private static int nBranco;
    private static int nPreto;
    private static int PBranco;
    private static int PPreto;
    private boolean[][] blocked;
    

    public Mapa() throws SlickException {
        this.mapa = new TiledMap("/base.tmx");
        WIDTH = this.mapa.getWidth();
        HEIGHT = this.mapa.getHeight();
        TILE_WIDTH = this.mapa.getTileWidth();
        TILE_HEIGHT = this.mapa.getTileHeight();
        this.tiles = identifyTiles();
        mapInfo = new Vertice[HEIGHT][WIDTH];
        nBranco = 40;
        nPreto = 40;
        PPreto = 200000;
        PBranco = 200000;
        gerarMapa();

    }

    public TiledMap getMapa() {
        return mapa;
    }

    public void setMapa(TiledMap mapa) {
        this.mapa = mapa;
    }

    public LinkedList<Integer> getTiles() {
        return tiles;
    }

    public void setTiles(LinkedList<Integer> tiles) {
        this.tiles = tiles;
    }

    public static int getWIDTH() {
        return WIDTH;
    }

    public static void setWIDTH(int WIDTH) {
        Mapa.WIDTH = WIDTH;
    }

    public static int getHEIGHT() {
        return HEIGHT;
    }

    public static void setHEIGHT(int HEIGHT) {
        Mapa.HEIGHT = HEIGHT;
    }

    public static int getTILE_WIDTH() {
        return TILE_WIDTH;
    }

    public static void setTILE_WIDTH(int TILE_WIDTH) {
        Mapa.TILE_WIDTH = TILE_WIDTH;
    }

    public static int getTILE_HEIGHT() {
        return TILE_HEIGHT;
    }

    public static void setTILE_HEIGHT(int TILE_HEIGHT) {
        Mapa.TILE_HEIGHT = TILE_HEIGHT;
    }

    public static Vertice[][] getMapInfo() {
        return mapInfo;
    }

    public static void setMapInfo(Vertice[][] mapInfo) {
        Mapa.mapInfo = mapInfo;
    }

    public boolean[][] getBlocked() {
        return blocked;
    }

    public void setBlocked(boolean[][] blocked) {
        this.blocked = blocked;
    }

    public static int getnBranco() {
        return nBranco;
    }

    public static void setnBranco(int nBranco) {
        Mapa.nBranco = nBranco;
    }

    public static int getnPreto() {
        return nPreto;
    }

    public static void setnPreto(int nPreto) {
        Mapa.nPreto = nPreto;
    }

    public static int getPBranco() {
        return PBranco;
    }

    public static void setPBranco(int PBranco) {
        Mapa.PBranco = PBranco;
    }

    public static int getPPreto() {
        return PPreto;
    }

    public static void setPPreto(int PPreto) {
        Mapa.PPreto = PPreto;
    }

    public final LinkedList<Integer> identifyTiles() {
        LinkedList<Integer> tileList = new LinkedList<>();
        tileList.add(this.getMapa().getTileId(0, 0, 0)); // Branco
        tileList.add(this.getMapa().getTileId(1, 0, 0)); // Rosa
        tileList.add(this.getMapa().getTileId(2, 0, 0)); // Amarelo
        tileList.add(this.getMapa().getTileId(3, 0, 0)); // Verde
        tileList.add(this.getMapa().getTileId(4, 0, 0)); // Azul
        tileList.add(this.getMapa().getTileId(5, 0, 0)); // Vermelho
        tileList.add(this.getMapa().getTileId(6, 0, 0)); // Marrom
        tileList.add(this.getMapa().getTileId(7, 0, 0)); // Cinza
        tileList.add(this.getMapa().getTileId(8, 0, 0)); // Preto   
        return tileList;
    }

    public static Mensagem getBranco() {
        return branco;
    }

    public static void setBranco(Mensagem branco) {
        Mapa.branco = branco;
    }

    public static Mensagem getPreto() {
        return preto;
    }

    public static void setPreto(Mensagem preto) {
        Mapa.preto = preto;
    }

    
    public void gerarMapa() {
        ArrayList<Integer> list = new ArrayList();

        for (int i = 0; i < WIDTH * HEIGHT; i++) {
            list.add(i);
        }
        int cont = 0;
        int i, id;
        int x, y;

        while (!list.isEmpty()) {
            i = (int) (Math.random() * list.size());
            id = list.get(i);
            x = id % WIDTH;
            y = id / WIDTH;
            if ((cont % this.getTiles().size() == 8 && y == 0) || (cont % this.getTiles().size() == 8 && y == HEIGHT - 1)) {
                cont++;
            } else {
                this.getMapa().setTileId(x, y, 0, this.getTiles().get(cont % this.getTiles().size()));
                mapInfo[y][x] = new Vertice(cont % this.getTiles().size(), id);
                list.remove(i);
                cont++;
            }
//        }
//        for (int j = 0; j < HEIGHT; j++) {
//            for (int k = 0; k < WIDTH; k++) {
//                System.out.print(mapInfo[j][k].getRotulo()+" ");
//            }
//            System.out.println("");
        }
        gerarArestas();
    }

    public void gerarArestas() {
        Vertice up;
        Vertice down;
        Vertice left;
        Vertice right;

        for (int i = 0; i < HEIGHT; i++) {
            for (int j = 0; j < WIDTH; j++) {
//                if(i == 0){
//                    if(j==0){
//                        down = new Vertice(this.mapInfo[i][j+1].getRotulo(), this.mapInfo[i][j+1].getId(), WIDTH);
//                        right = new Vertice(this.mapInfo[i+1][j].getRotulo(), this.mapInfo[i+1][j].getRotulo(), WIDTH);
//                        this.mapInfo[i][j].getArestas().add(new Aresta((down.getRotulo()*5+5), down));
//                        this.mapInfo[i][j].getArestas().add(new Aresta((right.getRotulo()*5+5), right));
//                    }
                if (i > 0) {
                    up = mapInfo[i - 1][j];
                    mapInfo[i][j].getArestas().add(new Aresta(up.getRotulo() * 5 + 5, up));
                    //System.out.println("UP = " + up.getRotulo() + " " + up.getPosx() + "" + up.getPosy());
                }

                if (i < HEIGHT - 1) {
                    down = mapInfo[i + 1][j];
                    mapInfo[i][j].getArestas().add(new Aresta(down.getRotulo() * 5 + 5, down));
                    //System.out.println("down = " + down.getRotulo() + " " + down.getPosx() + " " + down.getPosy());
                }

                if (j > 0) {
                    left = mapInfo[i][j - 1];
                    mapInfo[i][j].getArestas().add(new Aresta(left.getRotulo() * 5 + 5, left));
                    //System.out.println("LEFT = " + left.getRotulo() + " " + left.getPosx() + " " + left.getPosy());
                }

                if (j < WIDTH - 1) {
                    right = mapInfo[i][j + 1];
                    mapInfo[i][j].getArestas().add(new Aresta(right.getRotulo() * 5 + 5, right));
                    //System.out.println("RIGHT = " + right.getRotulo() + " " + right.getPosx() + " " + right.getPosy());
                }
                //System.out.println("[" + i + "]" + "[" + j + "] " + mapInfo[i][j].getRotulo());
//                for (Aresta arestas  : mapInfo[i][j].getArestas()) {
//                    System.out.print("["+arestas.getDestino().getPosx()+"]"+"["+arestas.getDestino().getPosy()+"] "+arestas.getDestino().getRotulo() + " ");
//                }
//                System.out.println("");
            }
            //System.out.println("");
        }

    }
}
